﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace Team6_Algorithms.Filters
{
   public  class GrayCombinedMasking
    {
       /// <summary>
       /// Dylan Snel
       /// </summary>
        public static int RedMean;

        /// <summary>
        /// Made by Dylan Snel
        /// Filter that combines a list of masks on a binary image
        /// And returns either the mean of the filters or the Max value
        /// </summary>
        /// <param name="B">the Source Image</param>
        /// <param name="MASK">List containing the masks</param>
        /// <param name="MAX">If true, returns the max value instead of the mean.</param>
        /// <returns>wheter the script ran succesfull</returns>
        public static int[,] applyFilter(Bitmap B, List<Mask> MASK, bool MAX, int TresHold)
        {
            


            Bitmap bSrc = (Bitmap)B.Clone();

            BitmapData BmData = B.LockBits(new Rectangle(0, 0, B.Width, B.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            BitmapData BmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            int[,] Directions = new int[B.Width, B.Height];
            int stride = BmData.Stride;

            System.IntPtr Scan0 = BmData.Scan0;
            System.IntPtr SrcScan0 = BmSrc.Scan0;

            unsafe
            {
                byte* p = (byte*)(void*)Scan0;
                byte* pSrc = (byte*)(void*)SrcScan0;

                p += ((MASK[0].Size - 1) / 2) * stride;
                p += ((MASK[0].Size - 1) / 2) * 3;
                pSrc += ((MASK[0].Size - 1) / 2) * stride;
                pSrc += ((MASK[0].Size - 1) / 2) * 3;

                int nOffset =stride - ( B.Width *3);
                int nWidth = B.Width - ((MASK[0].Size - 1) / 2);
                int nHeight = B.Height - ((MASK[0].Size - 1) / 2);
                int x=0,y=0;
                for (y = ((MASK[0].Size - 1) / 2); y < nHeight; ++y)
                {
                    for (x = ((MASK[0].Size - 1) / 2); x < nWidth; ++x)
                    {
                        int TempRed = 0, MaxValue = 0, Direction = 0;
                    
                
                        int i = 0;
                        foreach (Mask m in MASK)
                        {
                                                      
                            calculateMeans(pSrc, m, stride);

                            if (RedMean > MaxValue)
                            {
                                Direction = i;
                                MaxValue = RedMean;
                            }

                            TempRed += RedMean;
                            
                         
                            
                            i++;
                        }
                        if (RedMean <= TresHold && TresHold != 0)
                        {
                            RedMean = 0;
                            Direction = -1;
                        }
                        Directions[x , y] = Direction + 1;
                        Color useColor;
                        switch (Direction + 1)
                        {
                            case 1:
                                useColor = Color.Red;
                                break;

                            case 2:
                                useColor = Color.Blue;
                                break;
                            case 3:
                                useColor = Color.Yellow;
                                break;
                            case 4:
                                useColor = Color.Green;
                                break;

                            case 0:
                                useColor = Color.Black;
                                break;

                            default:
                                useColor = Color.White;
                                break;
                        }
                        p[0] = useColor.B;
                        p[1] = useColor.G;
                        p[2] = useColor.R;
                        /*
                        if (MAX == false)
                        {
                            RedMean = TempRed / MASK.Count;

                            p[0] = (byte)RedMean;
                            p[1] = (byte)RedMean;
                            p[2] = (byte)RedMean;
                        }
                        else
                        {
                            p[0] = (byte)MaxValue;
                            p[1] = (byte)MaxValue;
                            p[2] = (byte)MaxValue;
                        }
                        */
                        

                        p += 3;
                        // add 3 pixels to the address? possibly
                        // at least, this is moving through the pic
                        // or maybe 3 bytes
                        pSrc += 3;
                    }
                    // but then here we add the padding... at the end of every row
                    pSrc += -3 + ((MASK[0].Size - 1) / 2) * 3;
                    p += -3 + ((MASK[0].Size - 1) / 2) * 3;
                    p += nOffset;
                    pSrc += nOffset;
                }
                Console.WriteLine("x: " + x + "; y = " + y);
            }
            
            B.UnlockBits(BmData);
            bSrc.UnlockBits(BmSrc);

            return Directions;
        }


        /// <summary>
        /// Private function used to calculate the value of a mask
        /// </summary>
        /// <param name="P">pointer to Scan0 of the source bitmap</param>
        /// <param name="MASK"></param>
        /// <param name="STRIDE"></param>
        private static unsafe void calculateMeans(byte* P, Mask MASK, int STRIDE)
        {
            RedMean = 0;
        
            int yCounter = 0;
            int xCounter = 0;
            byte* CalcPointer = P;
            int Boundary = (MASK.Size - 1) / 2;
            for (int y = -Boundary; y <= Boundary; ++y)
            {

                for (int x = -Boundary; x <= Boundary; ++x)
                {
                    RedMean += CalcPointer[2 + (x * 3) + (y * STRIDE)] * MASK.MaskValues[xCounter][yCounter];
               

                    xCounter++;

                }
                xCounter = 0;
                yCounter++;
            }
            RedMean /= MASK.Total;
           

            RedMean += MASK.OffSet;
          
            if (RedMean > 255)
            {
                RedMean = 255;
            }
         
            if (RedMean < 0)
            {
                RedMean = 0;
            }
         



        }

    }

}